﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace Nirvana
{
    /// <summary>
    /// 对象绑定脚本，用于对象和名称相映射，这样find对象时，不用
    /// 关联具体对象obj，只关注name就可以了。就算obj变化都没事
    /// </summary>
    [AddComponentMenu("Nirvana/UI/Bind/UI Name Table")]
    public sealed class UINameTable : MonoBehaviour
    {
        [Serializable]
        public struct BindPair
        {
            [Tooltip("The name of this bind.")]
            public string Name;

            [Tooltip("The widget of this UI.")]
            public GameObject Widget;
        };

        [SerializeField]
        [Tooltip("The bind list.")]
        public List<BindPair> binds = new List<BindPair>();
        private Dictionary<string, GameObject> objMap;
        private static Comparison<BindPair> BindPairSort;
        public Dictionary<string, GameObject> Lookup
        {
            get
            {
                if (this.objMap == null)
                {
                    this.objMap = new Dictionary<string, GameObject>(StringComparer.Ordinal);
                    if (this.binds != null)
                    {
                        foreach (var p in binds) objMap.Add(p.Name, p.Widget);
                    }

                }
                return this.objMap;
            }
        }
        /// <summary>
        /// 查找节点，没有则查找所有子节点
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public GameObject Find(string key)
        {
            GameObject result;
            if (this.Lookup.TryGetValue(key, out result))
            {
                return result;
            }
            else
            {
                //直接深度查找孩子节点
                var go = GetChild(transform, key);
                if (go != null) return go.gameObject;
                else
                {
                    Debug.LogErrorFormat("Dont Find Child :{0} => {1}",gameObject.name, key);
                }
            }
            return null;
        }
        /// <summary>
        /// 从记录表中查找节点
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public GameObject FindTable(string key)
        {
            GameObject result;
            if (this.Lookup.TryGetValue(key, out result))
            {
                return result;
            }
            return null;
        }

        /// <summary>
        /// 支持深层孩子
        /// </summary>
        public Transform GetChild(Transform transform, string boneName)
        {
            Transform child = transform.Find(boneName);
            if (child == null)
            {
                foreach (Transform subChild in transform)
                {
                    child = GetChild(subChild, boneName);
                    if (child != null) return child;
                }
            }
            return child;
        }

        public bool Add(string key, GameObject obj)
        {
            if (this.objMap.ContainsKey(key))
            {
                return false;
            }
            this.objMap.Add(key, obj);
            BindPair item = default(BindPair);
            item.Name = key;
            item.Widget = obj;
            this.binds.Add(item);
            return true;
        }

        public void Sort()
        {
            if (BindPairSort == null)
                BindPairSort = new Comparison<BindPair>(
                (a, b) => {
                    return a.Name.CompareTo(b.Name);
                });

            this.binds.Sort(BindPairSort);
        }

        public BindPair[] Search(string key)
        {
            List<BindPair> list = new List<BindPair>();
            foreach (var p in this.binds)
            {
                if (p.Name.StartsWith(key))
                {
                    list.Add(p);
                }
            }
            return list.ToArray();
        }

    }
}

